import Axios, {
  type AxiosResponse,
  type AxiosRequestConfig,
  type AxiosError,
} from 'axios';
import qs from 'qs';
import { useLoginStore } from '@/stores/login';
import router from '@/router';

export const CONTENT_TYPE = 'Content-Type';

export const FORM_URLENCODED =
  'application/x-www-form-urlencoded; charset=UTF-8';

export const APPLICATION_JSON = 'application/json; charset=UTF-8';

export const TEXT_PLAIN = 'text/plain; charset=UTF-8';
/**
 * 接口白名单
 */
export const whitelist = ['/api/web/captcha/:number', '/api/web/login'];

/**
 * 匹配动态路由
 * @param url 请求路径
 * @returns
 */
const fetchUrl = (url: string) => {
  return whitelist.some((el) => {
    if (el.includes(':')) {
      const regString = el.split('/').reduce((c, n) => {
        if (n.startsWith(':')) {
          return c + '/' + '[\\w\\b]{1,}';
        }
        return c + '/' + n;
      });
      const REG = new RegExp(regString);
      return REG.test(url);
    }
    return el === url;
  });
};

// 创建axios实例
const service = Axios.create({
  baseURL: import.meta.env.VITE_GLOB_API_URL,
  timeout: Number(import.meta.env.VITE_GLOB_API_TIMEOUT),
});

// 请求拦截器
service.interceptors.request.use(
  (config) => {
    const { url } = config;
    if (url) {
      /**
       * 若是白名单接口，则不携带token信息
       */
      if (fetchUrl(url)) {
        return config;
      }

      /**
       * 非白名单需要携带token信息
       */
      const loginStore = useLoginStore();
      config.headers.set(
        loginStore.tokenInfo.tokenName,
        loginStore.tokenInfo.tokenValue,
      );
    }
    return config;
  },
  (error) => {
    return Promise.reject(error.response);
  },
);

// 响应拦截器
service.interceptors.response.use(
  (response) => {
    const { status, data, config } = response;
    if (
      config.responseType === 'arraybuffer' ||
      config.responseType === 'blob'
    ) {
      return {
        status: 200,
        msg: '成功',
        data,
      };
    }
    if (status === 200 && data.status === 200) {
      return data;
    }
    /**
     * 若token过期，则清楚token 重新登录
     */
    if (data.status === 401) {
      useLoginStore().clearToken()
      router.push({ name: 'login' });
    }
    window.$message.error(data.msg, { duration: 30000 });
    return Promise.reject(data.msg);
  },
  (error: AxiosError) => {
    let message = '';
    switch (error.response?.status) {
      case 400:
        message = '请求错误(400)';
        break;
      case 401:
        message = '未授权，请重新登录(401)';
        useLoginStore().clearToken();
        break;
      case 403:
        message = '拒绝访问(403)';
        break;
      case 404:
        message = '请求出错(404)';
        break;
      case 408:
        message = '请求超时(408)';
        break;
      case 500:
        message = '服务器错误(500)';
        break;
      case 501:
        message = '服务未实现(501)';
        break;
      case 502:
        message = '网络错误(502)';
        break;
      case 503:
        message = '服务不可用(503)';
        break;
      case 504:
        message = '网络超时(504)';
        break;
      case 505:
        message = 'HTTP版本不受支持(505)';
        break;
      default:
        message = `连接出错(${error.response?.status})!`;
    }
    window.$message.error(message, { duration: 30000 });
    return Promise.reject(error.response);
  },
);
/**
 * 导出axios request方法，
 * 注意返回的是Promise<RequestResponse<any>>，
 * 而不是 AxiosResponse<any,any>
 * @param config AxiosRequestConfig
 */
const request = (config: AxiosRequestConfig): Promise<RequestResponse<any>> =>
  service.request(config);
export { service };
// 导出示例
export default request;
